package com.web.common.sql;



import com.web.common.spring.SpringUtils;
import com.web.common.utils.StringUtils;
import com.web.mapper.CommonSqlMapper;
import com.web.utils.DateUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @Author liuyanlong
 * @Description
 * @Date 2020/3/15 14:19
 **/
public class CommonSqlUtill{
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    /**
     * @Author liuyanlong
     * @Description 检查结果转换为驼峰展示
     * @Date 2020/3/15 14:34
     **/
    public static List<Map<String, Object>> mapUnderscoreToCamelCase(List<Map<String, Object>> oldList) {
        List<Map<String, Object>> newList = new ArrayList<>(oldList.size());
        for (Map<String, Object> map : oldList) {
            Map<String, Object> newMap = new HashMap<>();
            for (String oldKey : map.keySet()) {
                Object value = map.get(oldKey);
                String newKey = oldKey;
                if (oldKey.indexOf("_") > 0) {
                    newKey = lineToHump(oldKey);
                }
                newMap.put(newKey, value);
                if (value instanceof Date) {
                    Date d = (Date) value;
                    String format = sdf.format(d);
                    newMap.put(newKey, format);
                }
            }
            newList.add(newMap);
        }
        return newList;
    }

    private static Pattern linePattern = Pattern.compile("_(\\w)");

    /**
     * 驼峰转下划线,效率比上面高
     */
    public static String lineToHump(String str) {
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 将map的属性转换成实体类的属性
     *
     * @param params 要更新的字段以及值
     * @param t      要更新的对象
     * @author liuyanlong
     */
    public static <T> T copyPropertiesInclude(Map<String, Object> params, Class<T> t) throws Exception {
        Constructor cons = t.getDeclaredConstructor((Class[]) null);
        //获取实例
        T bean = (T) cons.newInstance();
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field f : fields) {
            try {
                String key = f.getName();
                Object value = params.get(key);
                if (value == null) {
                    continue;
                }
                String fieldType = f.getType().getSimpleName();
                String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
                Method fieldSetMet = bean.getClass().getMethod(methodName, f.getType());
                if (params.containsKey(key)) {
                    if ("String".equals(fieldType)) {
                        fieldSetMet.invoke(bean, value);
                    } else if ("Date".equals(fieldType)) {
                        Date temp = DateUtils.parseDate(value);
                        fieldSetMet.invoke(bean, temp);
                    } else if ("Integer".equals(fieldType)
                            || "int".equals(fieldType)) {
                        Integer intval = Integer.parseInt(value.toString());
                        fieldSetMet.invoke(bean, intval);
                    } else if ("Long".equalsIgnoreCase(fieldType)) {
                        Long temp = Long.parseLong(value.toString());
                        fieldSetMet.invoke(bean, temp);
                    } else if ("Double".equalsIgnoreCase(fieldType)) {
                        Double temp = Double.parseDouble(value.toString());
                        fieldSetMet.invoke(bean, temp);
                    } else if ("Boolean".equalsIgnoreCase(fieldType)) {
                        Boolean temp = Boolean.parseBoolean(value.toString());
                        fieldSetMet.invoke(bean, temp);
                    } else if ("BigDecimal".equalsIgnoreCase(fieldType)) {
                        BigDecimal temp = new BigDecimal(value.toString());
                        fieldSetMet.invoke(bean, temp);
                    } else {
                        fieldSetMet.invoke(bean, value);
                    }
                }
            } catch (Exception e) {
                continue;
            }
        }
        return (T) bean;

    }

    /**
     * @Author liuyanlong
     * @Description 将map数组对象转换为实体对象
     * 这里做一个封装
     * @Date 2020/3/19 18:56
     **/
    public static <T> List<T> ListMapToListBean(List<Map<String, Object>> listm, Class<T> t)
            throws Exception {
        //获取类的 无参构造器
        Constructor cons = t.getDeclaredConstructor((Class[]) null);
        //获取实例
        T obj = (T) cons.newInstance();
        Object mapvo = ListMapToListBean(listm, obj);
        return (List<T>) mapvo;
    }
    public static List<Object> ListMapToListBean(List<Map<String, Object>> listm, Object obj)
            throws Exception {

        List<Object> list = new ArrayList<Object>();
        // 循环遍历出map对象
        for (Map<String, Object> m : listm) {
            // 调用将map转换为JavaBean的方法
            Object objs = mapToBean(m, obj);
            // 添加进list集合
            list.add(objs);
        }

        return list;
    }
    public static Object mapToBean(Map<String, Object> map, Object obj1) throws Exception {

        // 获取JavaBean中的所有属性

        Object obj = obj1.getClass().newInstance();
        Field[] field = null;
        List<Field> fieldList = new ArrayList<>();
        Class tempClass = obj1.getClass();
        while (tempClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
        }
        field = fieldList.toArray(new Field[0]);
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss.SSS");

        for (Field fi : field) {
            // 判断key值是否存在
            String fildname = addStringXhx(fi.getName());
            if (map.containsKey(fildname) || map.containsKey(fi.getName())) {
                // 获取key的value值
                String value = "";
                if (null == map.get(fildname)) {
                    if (StringUtils.isEmpty(fi.getName())) continue;
                    if (null == map.get(fi.getName())) continue;
                } else {
                    value = map.get(fildname).toString();
                }
                if (StringUtils.isEmpty(value)) {
                    Object o = map.get(fi.getName());
                    value = "";
                    if (o != null) {
                        value = map.get(fi.getName()).toString();
                    }
                }
                // 将属性的第一个字母转换为大写}
                String frist = fi.getName().substring(0, 1).toUpperCase();
                // 属性封装set方法
                String setter = "set" + frist + fi.getName().substring(1);
                // 获取当前属性类型
                Class<?> type = fi.getType();
                // 获取JavaBean的方法,并设置类型
                Method method = obj.getClass().getMethod(setter, type);

                // 判断属性为double类型
                if ("java.lang.String".equals(type.getName())) {

                    // 调用当前Javabean中set方法，并传入指定类型参数
                    method.invoke(obj, value);

                } else if ("int".equals(type.getName()) || "java.lang.Integer".equals(type.getName())) {

                    method.invoke(obj, Integer.parseInt(value));

                } else if ("double".equals(type.getName()) || "java.lang.Double".equals(type.getName())) {

                    method.invoke(obj, Double.valueOf(value));

                } else if ("char".equals(type.getName())) {

                    method.invoke(obj, value);

                }
                else if ("long".equals(type.getName())) {
                    method.invoke(obj, Long.parseLong(value));
                }
                else if (type.getName().contains("Long")) {
                    method.invoke(obj, Long.parseLong(value));
                }
                else if ("java.util.Date".equals(type.getName())) {

                    Date date = simpleDateFormat.parse(value);
                    method.invoke(obj, date);

                }
                else if ("java.math.BigDecimal".equals(type.getName())) {

                    method.invoke(obj, BigDecimal.valueOf(Double.valueOf(value)));

                }

            }
        }

        return obj;
    }
    private static String addStringXhx(String name) {
        StringBuilder stringBuilder = new StringBuilder(name.length() + 5);
        int len = name.length();
        for (int i = 0; i < len; i++) {
            char c = name.charAt(i);
            if (Character.isUpperCase(c)) {
                stringBuilder.append("_" + Character.toLowerCase(c));
            } else {
                stringBuilder.append(c);
            }

        }
        return stringBuilder.toString();

    }


    /**
     * @param sql 语句 t 返回的实体类
     * @Author liuyanlong
     * @Description
     * @Date 2020/5/1 16:52
     **/
    public static <T> List<T> getListBySql(String sql, Class<T> t) {
        List<Map<String, Object>> list = SpringUtils.getBean(CommonSqlMapper.class).querySql(sql);
        List<T> ts = null;
        try {
            ts = ListMapToListBean(list, t);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
    }

    public static <T> T getObjBySql(String sql, Class<T> t) {
        List<T> ts = getListBySql(sql, t);
        if (ts != null) {
            return ts.get(0);
        }
        return null;
    }


}
